/**
 * author:Administrator
 * date:2016/1/6
 * desc: test account
 *
 * -------account transaction--------
 * step 2-1: create acc2,acc3
 * step 2-2: transaction acc2->acc3, money < balance, should success
 * step 2-3: transaction acc2->acc3, money > balance, should fail, roll back
 * step 2-4: transaction acc2->-1(not exists account),should fail, roll back
 * step 2-5: delete test account
 */
"use strict";

var assert = require('assert');
var request = require('request');
var testUtils = require('./test_utils.js');

var httpPort = require('../config/index.js').http.port;
var __hostPort = 'http://localhost:' + httpPort;

var __acc1 = {
  name: 'foo',
  money: 99
};
var __acc2 = {
  name: 'foo2',
  money: 1000
};
var __trans1 = 1; // fine
var __trans2 = 12345; // too much
var __notExistAcc = -1;

var stepCreate;
function waitCreateDone(done) {
  if (!!stepCreate)done();
  else setTimeout(function () {
    waitCreateDone(done);
  }, 500);
}

var stepTrans = 0; // we have 3 transaction test, run in parallel
function waitTransDone(done) {
  if (stepTrans == 3)done();
  else setTimeout(function () {
    waitTransDone(done);
  }, 500);
}

var stepRead;
function waitReadDone(done) {
  if (!!stepRead)done();
  else setTimeout(function () {
    waitReadDone(done);
  }, 500);
}

describe('account transaction', function () {
  it('create', function (done) {
    var url = __hostPort + '/accounts';
    var createCnt = 0;
    // create acc1
    testUtils.postJson(url, __acc1, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      __acc1.id = data.account.id;
      if (++createCnt == 2) {
        stepCreate = 1;
        done();
      }
    });
    //create acc2
    testUtils.postJson(url, __acc2, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      __acc2.id = data.account.id;
      if (++createCnt == 2) {
        stepCreate = 1;
        done();
      }
    });
  });
});

describe('account transaction', function () {
  this.timeout(5000);
  before(function (done) {
    waitCreateDone(done);
  });

  it('transaction1 should success', function (done) {
    var url = __hostPort + '/accounts/transaction';
    var json = {
      from: __acc1.id,
      to: __acc2.id,
      money: __trans1
    };
    testUtils.postJson(url, json, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      stepTrans++;
      done();
    });
  });

  // transaction2, too much > balance, so should fail
  it('transaction2 should fail: not enough money', function (done) {
    var url = __hostPort + '/accounts/transaction';
    var json = {
      from: __acc1.id,
      to: __acc2.id,
      money: __trans2
    };
    testUtils.postJson(url, json, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(1, data.errcode);
      stepTrans++;
      done();
    });
  });

  // transaction2, to account not exist , so should fail
  it('transaction3 should fail: to account not exist', function (done) {
    var url = __hostPort + '/accounts/transaction';
    var json = {
      from: __acc1.id,
      to: __notExistAcc,
      money: __trans1
    };
    testUtils.postJson(url, json, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(1, data.errcode);
      stepTrans++;
      done();
    });
  });

});


describe('account transaction', function () {
  this.timeout(5000);
  before(function (done) {
    waitTransDone(done);
  });

  it('read after all transaction', function (done) {
    var cnt = 0;

    // check acc1
    var url1 = __hostPort + '/accounts/' + __acc1.id;
    var acc1money = __acc1.money - __trans1;
    request(url1, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      assert.equal(data.account.money, acc1money);
      if (++cnt == 2) {
        stepRead = 1;
        done();
      }
    });

    // check acc2
    var url2 = __hostPort + '/accounts/' + __acc2.id;
    var acc2money = __acc2.money + __trans1;
    request(url2, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      assert.equal(data.account.money, acc2money);
      if (++cnt == 2) {
        stepRead = 1;
        done();
      }
    });
  });
});


describe('account transaction', function () {
  this.timeout(5000);
  before(function (done) {
    waitReadDone(done);
  });
  it('cleanup', function (done) {
    var cnt = 0;
    // delete acc1
    var url1 = __hostPort + '/accounts/' + __acc1.id;
    testUtils.deleteJson(url1, null, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      if (++cnt == 2) {
        done();
      }
    });

    // delete acc2
    var url2 = __hostPort + '/accounts/' + __acc2.id;
    testUtils.deleteJson(url2, null, function (err, res, data) {
      assert.equal(!!err, false);
      if (typeof data === 'string') data = JSON.parse(data);
      assert.equal(0, data.errcode);
      if (++cnt == 2) {
        done();
      }
    });
  });
});